/**
 *
 */
package com.newer.config.shiro.realms;

import com.newer.biz.sys.auth.ShiroBiz;
import com.newer.biz.sys.role.RoleInfoBiz;
import com.newer.commons.result.BizResult;
import com.newer.dao.bean.sys.Menu;
import com.newer.dao.bean.sys.RolePermission;
import com.newer.dao.bean.sys.User;
import com.newer.dao.bean.sys.UserRole;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义域
 *
 * @author 寻添俊
 * 2018年3月7日-上午10:28:20
 */
public class ShiroAuthcRealm extends AuthorizingRealm {

    /**
     * Shiro业务操作
     */
    @Autowired
    ShiroBiz shiroBiz;

    /**
     * 角色相关业务操作
     */
    @Autowired
    RoleInfoBiz roleInfoBiz;


    /**
     * 用户授权操作
     * 注意:只有当遇到用户的权限的查询或访问的页面是需要权限或角色才能访问时,才会执行该方法
     * <p>
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 初始化认证对象
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 获取当前登录主体
        User users = (User) principals.getPrimaryPrincipal();

        // 判断角色信息查询是否正确
        if (CollectionUtils.isNotEmpty(users.getUserRoles())) {
            List<String> roleCodes = new ArrayList<>();
            // 循环每个角色信息
            for (UserRole userRole : users.getUserRoles()) {
                // 添加角色Code
                roleCodes.add(userRole.getRoleCode());
                // 根据角色信息查询权限信息
                BizResult<RolePermission> rolePermsResult = roleInfoBiz.queryRolePermissionByRoleId(userRole.getRoleId());
                if (rolePermsResult.isSuccess() && CollectionUtils.isNotEmpty(rolePermsResult.getResults())) {
                    for (RolePermission rolePermission : rolePermsResult.getResults()) {
                        authorizationInfo.addStringPermission(rolePermission.getPermissionCode());
                    }
                }
            }
            // 判断角色Codes是否为空
            if (CollectionUtils.isNotEmpty(roleCodes)) {
                // 添加角色授权
                authorizationInfo.addRoles(roleCodes);
            }
        }
        return authorizationInfo;
    }

    /**
     * 用户认证操作
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        // 获取用户名信息
        String loginName = (String) token.getPrincipal();
        // 查询用户信息
        BizResult<User> usersResult = shiroBiz.userLogin(loginName);
        SimpleAuthenticationInfo info = null;
        // 判断是否为空
        if (usersResult.isSuccess()) {
            // 获取结果
            User users = usersResult.getResult();
            // 获取简单的认证信息(相当于通过loginName和password生成秘钥和用户登录生成的秘钥进行比较)
            info = new SimpleAuthenticationInfo(users, users.getLoginPwd(),
                    getName());
            // 添加盐的值
            if (StringUtils.isNotBlank(users.getSalt())) {
                info.setCredentialsSalt(ByteSource.Util.bytes(users.getSalt()));
            }
            // 根据用户查询用户的所有角色
            BizResult<UserRole> userRoleResult = shiroBiz.findUserRoles(users.getId());

            if (userRoleResult.isSuccess()) {
                List<UserRole> userRoles = userRoleResult.getResults();
                users.setUserRoles(userRoles);
                BizResult<Menu> menuResult = shiroBiz.findUsersMenus(userRoles);
                // 判断信息查询是否正确
                if (menuResult.isSuccess()) {
                    users.setMenus(menuResult.getResults());
                }
            }
        }
        return info;
    }

    /**
     * 清空授权
     */
    public void clearAuthz() {
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }


    /**
     * 清除所有用户授权信息缓存.
     */
    public void clearAllCachedAuthorizationInfo() {
        Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
        if (cache != null) {
            for (Object key : cache.keys()) {
                cache.remove(key);
            }
        }
    }
}
